<template>
  <div class="menu-manage">
    <!-- 搜索和筛选区域 -->
    <div class="search-filter">
      <div class="search-item">
        <span class="label">菜单名称</span>
        <el-input v-model="searchForm.name" placeholder="请输入菜单名称" clearable></el-input>
      </div>
      <div class="search-item">
        <span class="label">状态</span>
        <el-select v-model="searchForm.status" placeholder="菜单状态" clearable>
          <el-option label="正常" value="1"></el-option>
          <el-option label="停用" value="0"></el-option>
        </el-select>
      </div>
      <el-button type="primary" @click="onSearch" class="search-btn">
        <el-icon><Search /></el-icon>搜索
      </el-button>
      <el-button @click="onReset" class="reset-btn">
        <el-icon><Refresh /></el-icon>重置
      </el-button>
    </div>

    <!-- 操作按钮区域 -->
    <div class="operation-btns">
      <el-button type="primary" plain @click="addRootMenu" class="add-btn">
        <el-icon><Plus /></el-icon>新增
      </el-button>
      <el-button plain @click="toggleExpand" class="toggle-btn">
        <el-icon><SwitchButton /></el-icon>展开/折叠
      </el-button>
      <div class="right-btns">
        <el-icon class="refresh-icon" @click="getMenuListData"><RefreshRight /></el-icon>
        <el-icon class="setting-icon"><Setting /></el-icon>
      </div>
    </div>

    <!-- 菜单列表 -->
    <el-table
      ref="menuTableRef"
      :data="menuList"
      style="width: 100%"
      row-key="id"
      :row-style="{ height: '50px' }"
      :tree-props="{ children: 'children' }"
      @expand-change="handleExpandChange"
      border
    >
      <el-table-column prop="label" label="菜单名称" min-width="220">
        <template #default="scope">
          <div class="menu-name-cell">
            <el-icon
              v-if="scope.row.children && scope.row.children.length > 0"
              @click="$refs.menuTableRef.toggleRowExpansion(scope.row)"
              class="tree-arrow"
            >
              <component :is="isRowExpanded(scope.row.id) ? ArrowDown : ArrowRight" />
            </el-icon>
            <span v-else class="tree-indent"></span>
            <el-icon v-if="scope.row.icon" class="menu-icon">
              <component :is="getIconComponent(scope.row.icon)" />
            </el-icon>
            <span class="menu-label">{{ scope.row.label }}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="图标" width="80" align="center">
        <template #default="scope">
          <el-icon class="menu-list-icon" v-if="scope.row.icon">
            <component :is="getIconComponent(scope.row.icon)" />
          </el-icon>
          <span v-else>-</span>
        </template>
      </el-table-column>
      <el-table-column prop="sort" label="排序" width="80" align="center"></el-table-column>
      <el-table-column prop="permission" label="权限标识" min-width="150"></el-table-column>
      <el-table-column prop="path" label="路由路径" min-width="250"></el-table-column>
      <el-table-column prop="status" label="显示状态" width="100" align="center">
        <template #default="scope">
          <el-tag :type="scope.row.status === 1 ? 'success' : 'info'" effect="light">
            {{ scope.row.status === 1 ? "正常" : "停用" }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="createTime" label="创建时间" min-width="160"></el-table-column>
      <el-table-column label="操作" width="150" fixed="right">
        <template #default="scope">
          <el-link type="primary" @click="handleEdit(scope.row)" class="operation-link">
            <el-icon><Edit /></el-icon>修改
          </el-link>
          <el-link type="primary" @click="addChildMenu(scope.row)" class="operation-link" v-if="scope.row.type < 2">
            <el-icon><Plus /></el-icon>新增
          </el-link>
          <el-link
            v-if="(!scope.row.children || scope.row.children.length === 0) && scope.row.label !== '控制台'"
            type="danger"
            @click="handleDelete(scope.row)"
            class="operation-link"
          >
            <el-icon><Delete /></el-icon>删除
          </el-link>
        </template>
      </el-table-column>
    </el-table>

    <!-- 菜单表单弹窗 -->
    <el-dialog
      :title="dialogTitle"
      v-model="dialogVisible"
      width="600px"
      :close-on-click-modal="false"
      :before-close="handleDialogClose"
    >
      <el-form :model="menuForm" :rules="menuFormRules" ref="menuFormRef" label-width="100px">
        <el-form-item label="上级菜单" prop="parentId">
          <el-input style="width: 450px" placeholder="请选择上级菜单" v-model="searchMenuName" clearable />
        </el-form-item>
        <el-tree
          class="menu-tree"
          :data="filteredMenuTree"
          :props="defaultProps"
          v-model="menuForm.parentId"
          accordion
          draggable
          @node-click="handleNodeClick"
          @node-drop="handleNodeDrop"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <el-icon v-if="data.icon" class="menu-icon">
                <component :is="getIconComponent(data.icon)" />
              </el-icon>
              <span class="menu-label"
                >{{ node.label }} {{ getChildCount(data) - 1 === 0 ? "" : "(" + (getChildCount(data) - 1) + ")" }}</span
              >
            </span>
          </template>
        </el-tree>
        <el-form-item label="菜单类型" prop="type">
          <el-radio-group v-model="menuForm.type">
            <el-radio :label="0">目录</el-radio>
            <el-radio :label="1">菜单</el-radio>
            <el-radio :label="2">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item :label="menuForm.type == 2 ? '按钮名称' : '菜单名称'" prop="label">
          <el-input
            v-model="menuForm.label"
            :placeholder="menuForm.type == 2 ? '请输入按钮名称' : '请输入菜单名称'"
          ></el-input>
        </el-form-item>
        <el-form-item label="菜单图标" prop="icon" v-if="menuForm.type != 2">
          <el-input v-model="menuForm.icon" placeholder="请输入图标名称" @input="isShowPanel = true"></el-input>
          <div style="width: 450px">
            <!-- v-model 相当于v-bind(:):modelValue + v-on:update:modelValue -->
            <IconSelector
              v-model="menuForm.icon"
              :filterText="menuForm.icon"
              :showPanel="isShowPanel"
              @close="isShowPanel = false"
              style="width: 100%"
            />
          </div>
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="menuForm.sort" :min="0" :max="999" controls-position="right"></el-input-number>
        </el-form-item>
        <el-form-item label="路由地址" prop="path" v-if="menuForm.type != 2">
          <el-input v-model="menuForm.path" placeholder="请输入路由地址"></el-input>
        </el-form-item>
        <el-form-item label="权限标识" prop="permission" v-if="menuForm.type != 0">
          <el-input v-model="menuForm.permission" placeholder="请输入权限标识"></el-input>
        </el-form-item>
        <el-form-item label="显示状态" prop="visible" v-if="menuForm.type != 2">
          <el-radio-group v-model="menuForm.status">
            <el-radio :label="1">显示</el-radio>
            <el-radio :label="0">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="handleDialogClose">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed, defineAsyncComponent, nextTick, watch } from "vue";
import { ElMessage, ElMessageBox, ElIcon } from "element-plus";
import {
  View,
  Search,
  Refresh,
  Plus,
  Setting,
  Delete,
  Edit,
  RefreshRight,
  ArrowDown,
  ArrowRight,
  SwitchButton,
  Close,
} from "@element-plus/icons-vue";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import { getMenuList, getMenuDetail, addMenu, updateMenu, deleteMenu } from "@/api/menu";
import IconSelector from "@/components/IconSelector";
import { useLayoutStore } from "@/stores/layout";

// 菜单列表数据
const menuList = ref([]);
const expandAll = ref(true);

const layoutStore = useLayoutStore();

// 搜索表单数据
const searchForm = ref({
  name: "",
  status: "",
});

// 菜单弹窗相关
const dialogVisible = ref(false);
const dialogType = ref("add"); // add 或 edit
const dialogTitle = computed(() => {
  return dialogType.value === "add" ? "新增菜单" : "编辑菜单";
});
const menuFormRef = ref(null);

// 菜单表单数据
const defaultMenuForm = {
  id: undefined,
  parentId: 0,
  label: "",
  type: 1,
  sort: 999,
  path: "",
  permission: "",
  icon: "",
  status: 1,
  oldType: null,
};

const menuForm = ref({ ...defaultMenuForm });

// 表单验证规则
const menuFormRules = {
  label: [{ required: true, message: "菜单名称不能为空", trigger: "blur" }],
  path: [{ required: true, message: "路由地址不能为空", trigger: "blur" }],
  component: [{ required: true, message: "组件路径不能为空", trigger: "blur" }],
};

const searchMenuName = ref("");

const isShowPanel = ref(false);

// 上级菜单默认属性
const defaultProps = {
  children: "children",
  label: "label",
};

// 上级菜单选项
const parentMenuOptions = ref([{ id: 0, label: "主目录", children: [] }]);

// 生成上级菜单选项
const generateParentMenuOptions = () => {
  // 过滤出目录和菜单
  const menuOptions = menuList.value
    .filter((item) => item.type < 2)
    .map((item) => {
      return {
        id: item.id,
        label: item.label,
        children: item.children
          ? item.children.filter((child) => child.type < 2).map((child) => ({ id: child.id, label: child.label }))
          : [],
      };
    });
  console.log(menuList.value);
  parentMenuOptions.value = [{ id: 0, label: "主目录", children: [] }, ...menuOptions];
};

// 获取菜单列表数据
const menuTableRef = ref(null);

// 存储展开行的ID
const expandedRowKeys = ref([]);

// 检查行是否展开 - 通过ID判断
const isRowExpanded = (rowId) => {
  return expandedRowKeys.value.includes(rowId);
};

// 检查行是否展开 - 通过对象判断
const isRowObjectExpanded = (row) => {
  if (!menuTableRef.value) return false;

  // 直接从表格实例获取展开状态
  const { store } = menuTableRef.value;
  return store.states.expandRows.value.some((expandedRow) => expandedRow.id === row.id);
};

// 监听expandAll变化，动态调整展开状态
watch(expandAll, (newValue) => {
  if (!menuTableRef.value || !menuList.value || menuList.value.length === 0) return;

  // 根据新的expandAll值调整所有行的展开状态
  nextTick(() => {
    toggleAllRows(menuList.value, newValue);
  });
});

// 计算属性: 过滤掉没有子节点的菜单，保留根菜单和有子节点的菜单
const filteredMenuTree = computed(() => {
  // 深拷贝菜单列表，避免修改原始数据
  const clonedMenuList = JSON.parse(JSON.stringify(menuList.value));
  let root = [];
  if (searchMenuName.value === "") {
    root = [
      {
        id: 0,
        label: "主目录",
        children: [...clonedMenuList],
      },
    ];
  } else {
    root = [
      {
        id: 0,
        label: "主目录",
        children: filterMenuTree(clonedMenuList, searchMenuName.value),
      },
    ];
  }
  return root;
});

// 递归过滤函数
const filterMenuTree = (menuList, searchText) => {
  return menuList
    .filter((item) => item.label.includes(searchText)) // 过滤当前层级的节点
    .map((item) => {
      // 如果当前节点有子节点，递归过滤子节点
      if (item.children && item.children.length > 0) {
        return {
          ...item,
          children: filterMenuTree(item.children, searchText), // 递归过滤子节点
        };
      }
      return item;
    });
};

// 初始化数据
onMounted(() => {
  getMenuListData();
});

// 处理展开/折叠变化事件
const handleExpandChange = (row, expanded) => {
  console.log("Row expansion changed:", row.id, expanded);

  // 更新expandedRowKeys
  const index = expandedRowKeys.value.indexOf(row.id);
  if (expanded && index === -1) {
    // 展开且不在列表中，添加
    expandedRowKeys.value.push(row.id);
  } else if (!expanded && index > -1) {
    // 折叠且在列表中，移除
    expandedRowKeys.value.splice(index, 1);
  }
};

// 递归处理所有行的展开/折叠
const toggleAllRows = (data, shouldExpand) => {
  if (!data || !data.length) return;

  data.forEach((row) => {
    if (row.children && row.children.length > 0) {
      // 设置当前行的展开状态
      menuTableRef.value.toggleRowExpansion(row, shouldExpand);

      // 更新expandedRowKeys
      const index = expandedRowKeys.value.indexOf(row.id);
      if (shouldExpand && index === -1) {
        expandedRowKeys.value.push(row.id);
      } else if (!shouldExpand && index > -1) {
        expandedRowKeys.value.splice(index, 1);
      }

      // 递归处理子行
      toggleAllRows(row.children, shouldExpand);
    }
  });
};

// 切换全部展开/折叠
const toggleExpand = () => {
  expandAll.value = !expandAll.value;
  // watch会处理后续展开/折叠操作
};

// 获取菜单列表数据
const getMenuListData = async () => {
  try {
    const response = await getMenuList(searchForm.value);
    if (response.success) {
      menuList.value = response.data || [];
      generateParentMenuOptions();

      // 重置expandedRowKeys
      expandedRowKeys.value = [];

      // 在下一个 tick 处理初始展开状态
      nextTick(() => {
        processInitialExpand();
      });
    } else {
      ElMessage.error(response.message || "获取菜单列表失败");
    }
  } catch (error) {
    console.error("获取菜单列表出错:", error);
    ElMessage.error("获取菜单列表失败");
  }
};

// 处理菜单列表数据的初始展开状态
const processInitialExpand = () => {
  if (!menuTableRef.value) return;

  // 等待表格渲染完成后处理初始展开状态
  nextTick(() => {
    toggleAllRows(menuList.value, expandAll.value);
  });
};

// 搜索功能
const onSearch = () => {
  getMenuListData();
};

// 重置功能
const onReset = () => {
  searchForm.value = {
    name: "",
    status: "",
  };
  getMenuListData();
};

// 处理菜单类型显示
const getMenuTypeLabel = (type) => {
  const types = {
    0: "目录",
    1: "菜单",
    2: "按钮",
  };
  return types[type] || "未知";
};

// 菜单类型对应的标签类型
const getMenuTypeTag = (type) => {
  const types = {
    0: "warning",
    1: "success",
    2: "info",
  };
  return types[type] || "";
};

// 重置表单
const resetForm = () => {
  menuForm.value = { ...defaultMenuForm };
  if (menuFormRef.value) {
    menuFormRef.value.resetFields();
  }
};

// 关闭弹窗
const handleDialogClose = () => {
  resetForm();
  dialogVisible.value = false;
};

// 新增根菜单
const addRootMenu = () => {
  dialogType.value = "add";
  resetForm();
  menuForm.value.parentId = 0;
  searchMenuName.value = "";
  dialogVisible.value = true;
};

// 新增子菜单
const addChildMenu = (row) => {
  dialogType.value = "add";
  resetForm();
  menuForm.value.parentId = row.id;
  menuForm.value.parentDisabled = true;
  dialogVisible.value = true;
};

// 编辑菜单
const handleEdit = async (row) => {
  dialogType.value = "edit";
  resetForm();
  searchMenuName.value = row.label;
  menuForm.value = { ...row, status: row.status, type: getMenuType(row), oldType: getMenuType(row), parentId: row.pid };
  dialogVisible.value = true;
};

// 判断row的类型 目录 菜单 按钮
const getMenuType = (row) => {
  if (row.pid === 0) {
    return 0;
  } else if (row.pid !== 0 && row.icon !== null) {
    return 1;
  } else {
    return 2;
  }
};

// 删除菜单
const handleDelete = (row) => {
  ElMessageBox.confirm(`确定删除菜单 "${row.label}" 吗？`, "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      try {
        const response = await deleteMenu({ id: row.id, type: getMenuType(row) });
        if (response.success) {
          ElMessage.success("删除成功");
          getMenuListData();
        } else {
          ElMessage.error(response.message || "删除失败");
        }
      } catch (error) {
        console.error("删除菜单出错:", error);
        ElMessage.error("删除失败");
      }
    })
    .catch(() => {
      // 取消删除
    });
};

// 处理状态变更
const handleStatusChange = async (row) => {
  try {
    const response = await updateMenu({
      id: row.id,
      status: row.status,
    });

    if (response.success) {
      ElMessage.success(`菜单已${row.status === 1 ? "启用" : "停用"}`);
    } else {
      // 如果更新失败，回退状态
      row.status = row.status === 1 ? 0 : 1;
      ElMessage.error(response.message || "更新状态失败");
    }
  } catch (error) {
    // 如果发生错误，回退状态
    row.status = row.status === 1 ? 0 : 1;
    console.error("更新菜单状态出错:", error);
    ElMessage.error("更新状态失败");
  }
};

// 提交表单
const submitForm = async () => {
  if (!menuFormRef.value) return;

  try {
    await menuFormRef.value.validate();
    console.log("提交表单:", menuForm.value);
    if (menuForm.value.type == 2 || menuForm.value.type == 1) {
      console.log("提交表单:", menuForm.value.permission);
      if (menuForm.value.permission === "" || menuForm.value.permission === null) {
        ElMessage.error("权限不能为空");
        return;
      }
      menuForm.value.visible = menuForm.value.status;
      const isAdd = dialogType.value === "add";
      const api = isAdd ? addMenu : updateMenu;
      const response = await api(menuForm.value);

      if (response.success) {
        ElMessage.success(isAdd ? "添加成功" : "修改成功");
        dialogVisible.value = false;
        getMenuListData();
        layoutStore.setMenuUpdate(true);
      } else {
        ElMessage.error(response.message || (isAdd ? "添加失败" : "修改失败"));
      }
    }
  } catch (error) {
    console.error("表单提交出错:", error);
    ElMessage.error("表单验证失败，请检查输入");
  }
};

// 动态加载图标组件
const getIconComponent = (iconName) => {
  if (!iconName) return null;
  return ElementPlusIconsVue[iconName];
};

onMounted(() => {
  getMenuListData();
});

// 计算子节点数量
const getChildCount = (menu) => {
  let count = 0;
  if (menu.children && menu.children.length > 0) {
    count = menu.children.reduce((acc, cur) => acc + getChildCount(cur), 0);
  }
  return count + 1;
};

// 处理树节点点击
const handleNodeClick = (data) => {
  if (data.id === 0) {
    menuForm.value.parentId = 0;
    searchMenuName.value = "主目录";
  } else {
    menuForm.value.parentId = data.id;
    searchMenuName.value = data.label;
  }
};

// 处理树节点拖拽
const handleNodeDrop = (draggingNode, dropNode, dropType) => {
  console.log("handleNodeDrop", draggingNode, dropNode, dropType);
};
</script>

<style scoped>
.menu-manage {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: calc(100vh - 84px);
}

/* 搜索过滤区样式 */
.search-filter {
  display: flex;
  align-items: center;
  padding: 18px 20px;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
  margin-bottom: 16px;
}

.search-item {
  display: flex;
  align-items: center;
  margin-right: 15px;
}

.search-item .label {
  margin-right: 8px;
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
}

.search-item :deep(.el-input),
.search-item :deep(.el-select) {
  width: 220px;
}

.search-btn,
.reset-btn {
  margin-right: 10px;
}

.advanced-search {
  margin-left: auto;
}

/* 操作按钮区域 */
.operation-btns {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
}

.add-btn,
.toggle-btn {
  margin-right: 10px;
}

.right-btns {
  display: flex;
  align-items: center;
  margin-left: auto;
}

.refresh-icon,
.setting-icon {
  font-size: 18px;
  margin-left: 15px;
  color: #606266;
  cursor: pointer;
}

.refresh-icon:hover,
.setting-icon:hover {
  color: #409eff;
}

/* 表格样式 */
.el-table {
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}

:deep(.el-table__header) {
  background-color: #f5f7fa;
}

:deep(.el-table__header-wrapper th) {
  background-color: #f5f7fa;
  color: #606266;
  font-weight: 600;
  height: 50px;
}

:deep(.el-table__row td) {
  padding: 10px 0;
}

:deep(.el-table__row .cell),
:deep(.el-table__header .cell) {
  display: flex;
  align-items: center;
  height: 100%;
}

:deep(.el-table .el-table__expand-icon) {
  display: none !important;
}

:deep(.el-table__indent) {
  padding-left: 0 !important;
}

:deep(.expanded-cell) {
  padding-left: 0 !important;
}

:deep(.el-table__placeholder) {
  display: none;
}

/* 菜单名称列样式 */
.menu-name-cell {
  display: flex;
  align-items: center;
  height: 100%;
}

.menu-icon {
  margin: 0 8px;
  font-size: 16px;
}

.menu-label {
  line-height: 1.5;
}

.tree-arrow {
  cursor: pointer;
  margin-right: 5px;
  font-size: 16px;
  color: #909399;
  flex-shrink: 0;
}

.tree-arrow:hover {
  color: #409eff;
}

.tree-indent {
  display: inline-block;
  width: 24px;
  flex-shrink: 0;
}

/* 操作列样式 */
.operation-link {
  display: inline-flex;
  align-items: center;
  margin-right: 12px;
  font-size: 13px;
}

.operation-link :deep(.el-icon) {
  margin-right: 3px;
  font-size: 14px;
}

/* 标签样式 */
:deep(.el-tag) {
  border-radius: 4px;
  padding: 0 10px;
  height: 28px;
  line-height: 28px;
}

/* 弹窗样式 */
:deep(.el-dialog) {
  border-radius: 8px;
}

:deep(.el-dialog__header) {
  border-bottom: 1px solid #f0f0f0;
  padding: 15px 20px;
}

:deep(.el-dialog__body) {
  padding: 20px;
}

:deep(.el-dialog__footer) {
  border-top: 1px solid #f0f0f0;
  padding: 15px 20px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
}

.menu-list-icon {
  font-size: 16px;
  width: 1em !important;
  height: 1em !important;
}

.menu-icon {
  margin: 0 8px;
  font-size: 16px;
  width: 1em !important;
  height: 1em !important;
}

/* 隐藏展开列 */
:deep(.el-table__expand-column) {
  width: 0 !important;
  padding: 0 !important;
  overflow: hidden;
}

:deep(.el-table__expand-icon) {
  display: none !important;
}

/* 展开内容样式 */
.expanded-content {
  display: none;
}

.menu-tree {
  position: relative;
  left: 100px;
  top: -10px;
  width: 81%;
}
</style>
